﻿#define _CRT_SECURE_NO_WARNINGS
// ↑ 将本行在代码放在第一行可以避免 scanf的报错问题（仅在VS编译器里）
//【初阶篇】55.数组_二维数组和数组越界
//【初阶篇】56.休息
//【初阶篇】57.数组_数组名
//【初阶篇】58.休息


#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<string.h>


//冒泡排序函数：核心思想，两个相邻元素互相比较
void bubble_sort(int arr[],int x)//数组写法//传参传数组名时实际是传递的数组首元素的地址，是一个指针类型

{
	int i = 0;
	int j = 0;
	for (i = 0; i < x-1; i++)
	{
		for (j = 0;j < x-1-i;j++)
		{
			if (arr[j] > arr[j+1])
			{
				int tmp = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = tmp;
			}
		}
	}
}



int main()
{
	//55.数组【二维数组】
	 {
	//创建
	int arr[3][4];//3行4列的数组
	//初始化
	int arr0[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};//3行4列的数组：元素依次摆放，空位补零
	int arr1[3][4] = { {1,2},{3,4},{5,6} };//利用大括号，可以按需要分组按组顺序放入对应行
	int arr2[][4] = { {1,2,3,4},{5,6} };//二维数组可以不定义行数但一定要定义列数，即每行元素个数//三维数组也只能省略第一维
	//使用//行和列均从0开始排序
	int i = 0;
	int j = 0;
		//输入
	printf("自定义3*4大小的数组\n列用空格，行用回车\n##输入区↓##\n");
	for (i = 0; i < 3; i++)
	{

		for (j = 0; j < 4; j++)
		{
			scanf("%d", &arr[i][j]);
		}
	}
		//输出
	for (i = 0; i < 3; i++)
	{
	
		for (j = 0; j < 4; j++)
		{
			printf("%d ", arr[i][j]);//输出元素
			printf("arr0[%d][%d]=%p\n",i ,j,&arr0[i][j]);//输出地址
		}
		printf("\n");
	}
	}

	//数组作为函数参数：两种方式传参1.数组2.指针
	//冒泡排序函数
	{
		int i = 0;
		int j = 0;
		int rearr[] = { 9,2,3,4,5,6,1,8,7 };
		int sz = sizeof(rearr) / sizeof(rearr[0]);
		bubble_sort(rearr, sz);
		for (i = 0; i < sz; i++)
		{
			printf("%d ", rearr[i]);//输出元素
		}
	}
	
	//57.数组_数组名
		//【一维】数组名 等价 首元素地址,有两个特殊情况不是，1.sizeof（数组名），表示整个数组，计算的是整个数组的大小，单位是字节2.&数组名，表示整个数组，取出的是整个数组的地址
	{
		printf("\n一维数组\n");
		int arr[10] = { 0 };
		int n = sizeof(arr);//1.sizeof（数组名），表示整个数组，计算的是整个数组的大小，单位是字节
		printf("%d\n", n);
		printf("数组名---------------------\n");
		printf("%p\n", arr);
		printf("%p\n", arr + 1);
		printf("取首元素地址---------------------\n");
		printf("%p\n", &arr[0]);
		printf("%p\n", &arr[0] + 1);
		printf("---------------------\n");
		printf("%p\n", &arr);//2. & 数组名，表示整个数组，取出的是整个数组的地址
		printf("%p\n", &arr + 1);

	}
		//【二维】数组名 也表示首元素的地址名，但是二维数组的首元素是指二维数组的第一行数组,如arr[3][4]的数组，首元素指的是二维数组第一行的4个元素大小的一维数组arr[0]
	{
		printf("二维数组\n");
		int arr[3][4] = { 0 };
		int n = sizeof(arr);//二维数组同样 1.sizeof（数组名），表示整个数组，计算的是整个数组的大小，单位是字节
		printf("%d\n", n);
		printf("数组名---------------------\n");
		printf("%p\n", arr);
		printf("%p\n", arr + 1);
		printf("取首元素地址---------------------\n");
		printf("%p\n", &arr[0]);
		printf("%p\n", &arr[0] + 1);
		printf("&数组名---------------------\n");
		printf("%p\n", &arr);//2. & 数组名，表示整个数组，取出的是整个数组的地址
		printf("%p\n", &arr + 1);

		//二维数组计算行数
		int x = sizeof(arr) / sizeof(arr[0]);
		printf("%d列\n", x);
		//二维数组计算列数
		int y = sizeof(arr[0]) / sizeof(arr[0][0]);
		printf("%d行\n", y);
	}


	return 0;
}
//【初阶篇】55.数组_二维数组和数组越界
	//【二维数组】：可以把二维数组想象成一维数组的数组
	//【数组越界】：使用小于0的下标或大于n-1的下标，会出现数组越界，这是一种错误操作，要避免，应在写代码时自行判断是否越界
	//【数组传参】数组作为函数参数：两种方式传参1.数组2.指针。传递数组名时，实际传递的是数组首元素地址（指针类型）
//【初阶篇】57.数组_数组名
	//【一维】数组名 <<--等价-->> 首元素地址,有两个特殊情况不是
		// 1.sizeof（数组名），表示整个数组，计算的是整个数组的大小，单位是字节
		// 2.&数组名，表示整个数组，取出的是整个数组的地址
	//【二维】数组名 等价 首元素地址
		//【注意】【二维】数组的首元素是指二维数组的第一行数组,如arr[3][4]的数组，首元素指的是二维数组第一行的4个元素大小的一维数组arr[0]

